% -*- mode: prolog -*-
% -*- coding: utf-8 -*-


% cmap2owl -- Helper application to convert from concept maps to OWL ontologies
% Copyright (c) 2008-2013  Rodrigo Rizzi Starr
%  
% Permission is hereby granted, free of charge, to any person obtaining a copy
% of this software and associated documentation files (the "Software"), to deal
% in the Software without restriction, including without limitation the rights
% to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
% copies of the Software, and to permit persons to whom the Software is
% furnished to do so, subject to the following conditions:
%  
% The above copyright notice and this permission notice shall be included in all
% copies or substantial portions of the Software.
%  
% THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
% IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
% FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
% AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
% LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
% OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
% SOFTWARE.


%% Utility functions
singleton(Set) :- length(Set, L), L == 1.
empty(Set) :- length(Set, L), L == 0.
notSingleton(Set) :- length(Set, L), L > 1.
notEmpty(Set) :- length(Set, L), L > 0.


%% Abstraction layer

% Dynamics for concept map representation
:- dynamic conceptCM/1.
:- dynamic linkingPhraseCM/1.
:- dynamic hasLabelCM/2.
:- dynamic hasLabelCMlower/2.
:- dynamic relationCM/3.
:- dynamic label/2.
:- dynamic llabel/2.

% Representation of equality of elements
:- dynamic equals/2.

% Something is always equal to itself
inEquals(Equal) :- equals(_, EqSet), member(Equal, EqSet).
inEquals(Element, Equal) :- equals(Element, EqSet), member(Equal, EqSet).

allNamesOf(Element, NameSet) :- equals(Element, EqSet),
                                append(EqSet, [Element], NameSet).

% Representing concepts
concept(Concept):- conceptCM(Concept),
                   \+ inEquals(Concept).
		   
equivalentConcept(Concept, Concept) :- concept(Concept).
equivalentConcept(Concept, Equal) :- inEquals(Concept, Equal),
                                     concept(Concept).


linkingPhrase(Relation) :- linkingPhraseCM(Relation),
                           \+ inEquals(Relation).
			   
equivalentLinkingPhrase(LinkingPhrase, LinkingPhrase) :- linkingPhrase(LinkingPhrase).
equivalentLinkingPhrase(LinkingPhrase, Equal) :- inEquals(LinkingPhrase, Equal),
                                                 linkingPhrase(LinkingPhrase).


label(Element, Label) :- hasLabelCM(Element, Label).
llabel(Element, Label) :- hasLabelCMlower(Element, Label).
						  
labels(ElSet, LabelSet) :- setof(Label,
                                 (member(Element, ElSet), label(Element, Label)),
                                 LabelSet).

:- dynamic relationBetween/3.  % Some rules may declare new types of relations
relationBetween(LinkingPhrase, From, To) :- relationCM(EqualLinkingPhrase, EqualFrom, EqualTo),
                                            equivalentLinkingPhrase(LinkingPhrase, EqualLinkingPhrase),
                                            equivalentConcept(From, EqualFrom),
                                            equivalentConcept(To, EqualTo).

fromPartRelation(Relation, From) :- relationBetween(Relation, From, _).
toPartRelation(Relation, To) :- relationBetween(Relation, _, To).

fromSetRelation(Relation, FromSet) :- setof(From,
                                            fromPartRelation(Relation, From),
                                            FromSet).
toSetRelation(Relation, ToSet) :- setof(To,
                                        toPartRelation(Relation, To),
                                        ToSet).
relationSet(Relation, FromSet, ToSet) :- fromSetRelation(Relation, FromSet),
                                         toSetRelation(Relation, ToSet).

%% Basic rule data: these predicates will be about other predicates
:- dynamic isTrue/1.
:- dynamic isFalse/1.

% An inference group is used to determine 'possibility'. A Predicate is only
% possible if none of its group participants is either true or false
:- dynamic inferenceGroup/2.   % The first arg is the name of the group, the
                               % second a list of options

inferenceResult(Group, Predicate) :- inferenceGroup(Group, List),
                                     member(Predicate, List).

% Tells when a Predicate is possible (neither true nor false)
possible(Predicate) :- inferenceResult(_, Predicate),
                       call(Predicate),
                       \+ isTrue(Predicate),
                       \+ isFalse(Predicate).

% Tells when a Predicate is on the positive side (that is, it is true or at
% least possible)
positive(Predicate) :- isTrue(Predicate); possible(Predicate).
negative(Predicate) :- isFalse(Predicate); possible(Predicate).

% If a predicate member of an infereceGroup is true, automatically all other
% members are false
isFalse(X) :- inferenceGroup(_, List),
              member(Y,List),
              isTrue(Y),
              member(X, List),
              X \== Y, 
              X =.. [_|Args],
              Y =.. [_|Args].
              
%% Test data
% Load file: ['basicInference.pl'].
%['concept.pl', 'testData.pl'].
%% :buffer:prolog:
